home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume14 / nntp1.5 / part07 < prev    next >
Encoding:
Internet Message Format  |  1988-04-19  |  51.4 KB

  1. Subject:  v14i053:  Network News Transfer Protocol, version 1.5, Part07/09
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Phil Lapsley <phil@ucbvax.berkeley.edu>
  7. Posting-number: Volume 14, Issue 53
  8. Archive-name: nntp1.5/part07
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 7 (of 9)."
  17. # Contents:  ./common/README ./server/misc.c ./support/nntp_awk
  18. #   ./xmit/nntp_awk
  19. # Wrapped by rsalz@fig.bbn.com on Tue Apr 19 18:16:47 1988
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f './common/README' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'./common/README'\"
  23. else
  24. echo shar: Extracting \"'./common/README'\" \(11756 characters\)
  25. sed "s/^X//" >'./common/README' <<'END_OF_FILE'
  26. X     You will need to customize common/conf.h to get the server,
  27. support, and client programs running on your system.  Unfortunately,
  28. X"rrn" has its own ideas of where to look for configuration information,
  29. so there is some duplication here.
  30. X
  31. X    >>> Also, you should see README.SYSV if you are compiling this on
  32. X    >>> a System V machine, as there is some extra stuff you need to do.
  33. X
  34. X     This is sort of a walk through conf.h so you can get some idea of
  35. what parameters need to be changed.  You should probably print this
  36. file out (or keep it in a separate window if you're on a workstation)
  37. and edit conf.h as you read through it.  For each #define in conf.h,
  38. the default value is listed in parenthesis after its name in this
  39. document.  Manual entries mentioned here are in the "doc" directory of
  40. the NNTP distribution.
  41. X
  42. X     First are some compile-time type options, for compiling in
  43. certain code.  The options should be "#undef"ed if you don't want
  44. them, and "#defined" if you do.
  45. X
  46. ALONE        (undefined)
  47. X
  48. X     Defines whether we're a stand alone version of the server, or
  49. whether we're running under inetd.  Define this if you do NOT have inetd.
  50. If you do have inetd, keep it undef'ed.
  51. X
  52. FASTFORK    (undefined)
  53. X
  54. X     If ALONE is defined, then this option tells us not to read the
  55. active file when we fork, but rather for the parent daemon to re-read
  56. it every READINTVL (below) seconds.  This should make forking off children
  57. a little bit faster.
  58. X
  59. BSD_42        (undefined)
  60. X
  61. X     If you have a 4.2 BSD system (as opposed to a 4.3 BSD system),
  62. this needs to be defined.  Really it does only two things: changes
  63. the log level to be compatible with 4.2, and automatically defines
  64. DBM (below).  If, somehow, you already have ndbm, then you should
  65. kill the lines which auto-define it.
  66. X
  67. DBM        (undefined)
  68. X
  69. X     If you don't have the ndbm routines in your standard library (i.e.,
  70. if you're not running 4.3 BSD), you'll have to define this; all it
  71. does is replace the ndbm calls with the earlier, unwieldy dbm calls.
  72. X
  73. X>>> If you define DBM, be sure to edit server/Makefile to have  "-ldbm"
  74. X>>> on the LIBS line, i.e.
  75. X
  76. X    LIBS = -ldbm
  77. X
  78. NDBM        (defined)
  79. X
  80. X     Define if you have the 4.3BSD ndbm routines.
  81. X
  82. USGHIST        (undefined)
  83. X
  84. X     Define if you don't use dbm/ndbm for the history file, but instead
  85. you use the USG-style history file format.  IF YOU DO NOT DEFINE EITHER
  86. DBM OR NDBM ABOVE, THIS IS THE DEFAULT.
  87. X
  88. USG        (undefined)
  89. X
  90. X     Compiles in code to support System V; some of these appear down
  91. below.  This is enough to get things to compile on an HPUX system,
  92. which is as close as I come to Sys V.  If I would only listen to
  93. Stan Barber, this would be more complete.
  94. X
  95. vfork        (undefined)
  96. X
  97. X     If you DON'T have vfork, replace this line with:
  98. X
  99. X#define    vfork    fork
  100. X
  101. If you DO have vfork, do nothing.
  102. X
  103. SYSLOG        (LOG_NEWS)
  104. X
  105. X     nntpd uses the syslog system to report errors, and optionally, to
  106. log usage statistics.  If SYSLOG is defined, errors will be
  107. reported via the syslog() library routine; if it is not defined, no errors
  108. will be reported.
  109. X
  110. X     If you just define SYSLOG, only errors will be reported.  If you
  111. want more information, such as statistics, you should define LOG, below.
  112. Defining LOG will cause additional information besides errors to be
  113. logged via SYSLOG.
  114. X
  115. X     If you have syslog(), define SYSLOG to be the name of the facility
  116. under which nntpd should log things.  If you are using FAKESYSLOG
  117. above, it really doesn't matter what facility name you choose; LOG_NEWS
  118. is fine.
  119. X
  120. LOG        (undefined)
  121. X
  122. X     When LOG is defined, we log copious amounts of information via
  123. syslog to a special file.  One a busy system like ucbvax, this produces
  124. about 100K of log information per day.  Look in ../server/SYSLOG to
  125. get an idea of what will be logged.  You can use the scripts
  126. provided in ../support to produce statistics on your NNTP server if
  127. you run with LOG.
  128. X
  129. FAKESYSLOG    (undefined)
  130. X
  131. X     This is useful if your system doesn't support syslog, but you'd
  132. like logging none the less.  By defining FAKESYSLOG to be the name of
  133. a file, e.g., "/usr/lib/news/nntplog", you can have all nntp messages
  134. logged to that file, ala syslog.  If you define FAKESYSLOG, you must
  135. define LOG and SYSLOG, below.  The code for the fake syslog routines
  136. are in ../server/fakesyslog.c, and are largely joe-code.
  137. X
  138. IHAVE_DEBUG    (undefined)
  139. X
  140. X     Enables logging of each message-id as it is offered via the IHAVE
  141. command.  This produces huge log files, but is useful if you suspect
  142. a site is repeatedly offering the same article to your site after you
  143. have rejected it.
  144. X
  145. XXHDR        (defined)
  146. X
  147. X     Enables the XHDR command, which is an extention of the NNTP spec.
  148. XXHDR allows client programs to see header lines (e.g., subject) from
  149. an article or range of articles.  This allows the '=' command in rn
  150. to be much faster, IF AND ONLY IF your server machine is fast.  Since
  151. this command foists off work on the server, it may be better to leave this
  152. undefined if your server machine is heavily loaded.
  153. X
  154. SUBNET        (undefined)
  155. X
  156. X     If you are running 4.3 BSD or have support for subnets on
  157. your local net, this will include subnet support for the access
  158. file.  Basically, a routine goes out and looks at all your ethernet
  159. interfaces, and figures out subnet masks from them.  It then
  160. uses these to resolve subnets from IP addresses.
  161. X
  162. DAMAGED_NETMASK    (undefined)
  163. X
  164. X     4.3 supports subnet masks of any bit-width, but user programs
  165. are *very* hard pressed to deal with masks which are not a multiple
  166. of 8 bits wide.  If you have a weird netmask, define DAMAGED_NETMASK.
  167. The code which uses it is in server/subnet.c.
  168. X
  169. NETMASK        (undefined)
  170. X
  171. X     The code in server/subnet.c wants to use 4BSD ioctls to determine
  172. the subnet masks for each network interface.  However, you may be able
  173. to support subnets without having such ioctls (HPUX is an example of
  174. such a system; SunOS 3.3 is another).  If you will be satisfied by
  175. having a compiled-in netmask, define NETMASK to be a hex constant
  176. describing your netmask (e.g., 0xffffff00).  You must also define
  177. SUBNET as well.
  178. X
  179. DECNET        (undefined)
  180. X
  181. X     Compile in DECNET support into the server and clientlib.
  182. This works under Ultrix (and not VMS!).
  183. X
  184. GHNAME        (defined)
  185. X
  186. X     Defined if you want to use the 4BSD gethostname() call to
  187. determine the name of your system.  This #define is only used
  188. by the mini-inews when posting news.  Some reasons you might not
  189. want to use this are: if your UUCP/news name is different than
  190. your internet name; if your gethostname() currently doesn't
  191. return fully-qualified names (e.g., 4.2) but you may "upgrade"
  192. to 4.3 (and return fq'd names) shortly, and you'd rather not
  193. have to recompile news...  See UUNAME below.
  194. X
  195. UUNAME        (undefined)
  196. X
  197. X     If this is defined, mini-inews will get the hostname out
  198. of /etc/uucpname or /local/uucpname.
  199. X
  200. X>>>    If GHNAME and UUNAME are undefined, mini-inews will    <<<
  201. X>>>    get the host name from /usr/include/whoami.h        <<<
  202. X
  203. FCNTL        (defined if SYSV is defined)
  204. X
  205. X     Some systems define things like O_RDONLY, etc. in <fcntl.h>.
  206. If FCNTL is defined, <fcntl.h> will be included.
  207. X
  208. NDIR        (defined if SYSV is defined)
  209. X
  210. X     Uses the ndir compatability library, and includes <ndir.h>.
  211. X
  212. TIMEOUT        (2 hours)
  213. X
  214. X     If a server is idle in command mode for TIMEOUT amount of time,
  215. it will close the connection with an error message.  This prevents
  216. old servers from clogging the system.  Timeout should be at least two
  217. hours so people can go eat lunch and leave an rn on their terminal.
  218. X
  219. XXFER_TIMEOUT    (30 minutes)
  220. X
  221. X     This is like TIMEOUT, above, but takes effect when the server is
  222. receiving news via IHAVE or POST.  If at least one line is not received
  223. in XFER_TIMEOUT amount of time, the server aborts with an error.
  224. X
  225. DOMAIN        ("uucp")
  226. X
  227. X     If domain is defined, it specifies that whatever it is defined
  228. as will be appended to host names; this is for posting news when
  229. your hostname() doesn't return your fully-qualified domain name.
  230. If your hostname system call does return a fully-qualified name,
  231. simply undef DOMAIN.
  232. X
  233. X
  234. SERVER_FILE    ("/usr/local/lib/rn/server")
  235. X
  236. X     This file contains the name of the machine which runs the
  237. news server.  Mini-inews, rrn, and getactive all use the contents
  238. of this file.  The idea behind this is that you don't have to have the server
  239. compiled into anything, and can have the same binaries across
  240. machines which have different news servers.
  241. X
  242. X     You must edit this file, and add a single line which contains
  243. the name of the news server for each machine which runs rrn.
  244. X
  245. X     If you have multiple news servers on your network, users can
  246. select which one they want to use via the NNTPSERVER environment
  247. variable, which will override the contents of SERVER_FILE.  Simply
  248. set NNTPSERVER to be the name of the machine whose news server you
  249. want to use.
  250. X
  251. X     If you are afraid of people abusing a particular news server
  252. via NNTPSERVER, you should edit the access file for that news server
  253. accordingly.  Security begins at home.
  254. X
  255. X>>> rrn, mini-inews, and getactive NO LONGER have compiled in server names <<<
  256. X>>> Be sure to create the SERVER_FILE as mentioned above, or you'll lose!  <<<
  257. X
  258. POSTER        ("usenet")
  259. X
  260. X     If your nntpd is run as root, nntpd will attempt to setuid()
  261. and setgid() to the uid and gid of whoever POSTER is defined as.
  262. If your nntpd isn't running as root (i.e., it might run as "usenet"),
  263. either undefine this, or define it to be a user which exists but
  264. is not used -- the setuid will fail in any event.
  265. X
  266. Next, we have some common files:
  267. X
  268. ACTIVE_FILE    ("/usr/lib/news/active")
  269. X
  270. X     Specifies the location of the "active" file.
  271. X
  272. ACCESS_FILE    ("/usr/lib/news/nntp_access")
  273. X
  274. X     Specifies the location of the remote access file.
  275. X     See the manual entry, nntpd.8c, for a better explanation.
  276. X     A sample access file is in ../support/access_file.
  277. X
  278. HISTORY_FILE    ("/usr/lib/news/history")
  279. X
  280. X     Specifies the location of the "history" file.
  281. X     This is used with NEWNEWS and ARTICLE/HEAD/BODY/STAT when
  282. X     given an message-id argument.
  283. X
  284. INEWS        ("/usr/lib/news/inews")
  285. X
  286. X     Specifies the location of inews, for posting.  Note that this
  287. X     is NOT the same as the mini-inews in the inews directory
  288. X     supplied with the NNTP distribution, which should only
  289. X     be installed on client machines.  INEWS should be the pathname
  290. X     of real, live, honest-to-God inews.  Your inews may be
  291. X     in a different place, such as /usr/bin/inews.
  292. X
  293. SPOOLDIR    ("/usr/spool/news/")
  294. X
  295. X     This is the directory where news is stored.  Note that
  296. X     the trailing / is important.
  297. X
  298. RNEWS        ("/usr/bin/rnews")
  299. X
  300. X     Specifies the location of the rnews program which is used
  301. X     for dealing with news received from other systems via the
  302. X     IHAVE command; it is often a link to inews.
  303. X
  304. STAT_FILE    ("/usr/lib/news/mgdstats")
  305. X
  306. X     NOTE: THIS IS NOT USED, BUT REMAINS FOR COMPATABILITY.
  307. X     When the support program "mkgrdates" is run, it keep stats
  308. X     in a file to tell whether or not to rebuild its database
  309. X     the next time it is run; this is the file the stats are kept
  310. X     in.  Needless to say, it must be writable by whatever user-id
  311. X     runs "mkgrdates".  See the manual entry "mkgrdates.8c" for
  312. X     more info.
  313. X
  314. NGDATE_FILE    ("/usr/lib/news/groupdates")
  315. X
  316. X     NOTE: THIS IS NOT USED, BUT REMAINS FOR COMPATABILITY.
  317. X     Specifies the location of the newsgroup creation date file.
  318. X     See the manual entry for both nntpd.8c and mkgrdates.8c for
  319. X     more info.
  320. X
  321. READINTVL    (600 seconds)
  322. X
  323. X     If the server is compiled with FASTFORK and ALONE, then this number
  324. X     tells how often to check if the active file has changed (and to
  325. X     read it in if it has changed since the last time).  See README
  326. X     in the "server" directory of the NNTP distribution.  If you are
  327. X     not compiled with FASTFORK and ALONE (hint: you're not going to),
  328. X     don't worry about this.
  329. X
  330. END_OF_FILE
  331. if test 11756 -ne `wc -c <'./common/README'`; then
  332.     echo shar: \"'./common/README'\" unpacked with wrong size!
  333. fi
  334. # end of './common/README'
  335. fi
  336. if test -f './server/misc.c' -a "${1}" != "-c" ; then 
  337.   echo shar: Will not clobber existing file \"'./server/misc.c'\"
  338. else
  339. echo shar: Extracting \"'./server/misc.c'\" \(11174 characters\)
  340. sed "s/^X//" >'./server/misc.c' <<'END_OF_FILE'
  341. X#ifndef lint
  342. static char    *sccsid = "@(#)misc.c    1.25    (Berkeley) 2/6/88";
  343. X#endif
  344. X
  345. X#include "../common/conf.h"
  346. X
  347. X#include "common.h"
  348. X
  349. X/*
  350. X * open_valid_art -- determine if a given article name is valid;
  351. X *        if it is, return a file pointer to the open article,
  352. X *        along with a unique id of the article.
  353. X *
  354. X *    Parameters:    "artname" is a string containing the
  355. X *            name of the article.
  356. X *            "id" is space for us to put the article
  357. X *            id in.
  358. X *
  359. X *    Returns:    File pointer to the open article if the
  360. X *            article is valid; NULL otherwise
  361. X *
  362. X *    Side effects:    None.
  363. X */
  364. X
  365. FILE *
  366. open_valid_art(artname, id)
  367. X    char        *artname;
  368. X    char        *id;
  369. X{
  370. X    static int    crnt_art_num;
  371. X    static char    crnt_art_id[MAXBUFLEN];
  372. X    int        fd;
  373. X    struct stat    statbuf;
  374. X
  375. X    if (art_fp != NULL) {
  376. X        if (crnt_art_num == atoi(artname)) {
  377. X            if (fseek(art_fp, (long) 0, 0) < 0)
  378. X                close_crnt();
  379. X            else {
  380. X                (void) strcpy(id, crnt_art_id);
  381. X                return (art_fp);
  382. X            }
  383. X        } else 
  384. X            close_crnt();
  385. X    }
  386. X
  387. X    art_fp = fopen(artname, "r");
  388. X
  389. X    if (art_fp == NULL)
  390. X        return (NULL);
  391. X
  392. X    fd = fileno(art_fp);
  393. X
  394. X    if (fstat(fd, &statbuf) < 0) {
  395. X        close_crnt();
  396. X        return (NULL);
  397. X    }
  398. X
  399. X    if ((statbuf.st_mode & S_IFREG) != S_IFREG) {
  400. X        close_crnt();
  401. X        return (NULL);
  402. X    }
  403. X
  404. X    get_id(art_fp, id);
  405. X    (void) strcpy(crnt_art_id, id);
  406. X    crnt_art_num = atoi(artname);
  407. X    return (art_fp);
  408. X}
  409. X
  410. X
  411. X/*
  412. X * gethistent -- return the path name of an article if it's
  413. X * in the history file.
  414. X *
  415. X *    Parameters:    "msg_id" is the message ID of the
  416. X *            article, enclosed in <>'s.
  417. X *
  418. X *    Returns:    A char pointer to a static data area
  419. X *            containing the full pathname of the
  420. X *            article, or NULL if the message-id is not
  421. X *            in thef history file.
  422. X *
  423. X *    Side effects:    opens dbm database
  424. X *            (only once, keeps it open after that).
  425. X *            Converts "msg_id" to lower case.
  426. X */
  427. X
  428. X#ifndef NDBM
  429. X# ifndef DBM
  430. X#  ifndef USGHIST
  431. X#   define USGHIST
  432. X#  endif not USGHIST
  433. X# endif not DBM
  434. X#endif not DBM
  435. X
  436. char *
  437. gethistent(msg_id)
  438. X    char        *msg_id;
  439. X{
  440. X    char        line[MAXBUFLEN];
  441. X    char        *tmp;
  442. X    register char    *cp;
  443. X    long        ltmp;
  444. X    static char    path[MAXPATHLEN];
  445. X#ifdef USGHIST
  446. X    char        *histfile();
  447. X    register int    len;
  448. X#else not USGHIST
  449. X#ifdef DBM
  450. X    static int    dbopen = 0;
  451. X    datum        fetch();
  452. X#else not DBM
  453. X    static DBM    *db = NULL;    /* History file, dbm version */
  454. X#endif DBM
  455. X    datum         key, content;
  456. X#endif USGHIST
  457. X    static FILE    *hfp = NULL;    /* history file, text version */
  458. X
  459. X    for (cp = msg_id; *cp != '\0'; ++cp)
  460. X        if (isupper(*cp))
  461. X            *cp = tolower(*cp);
  462. X
  463. X#ifdef USGHIST
  464. X    hfp = fopen(histfile(msg_id), "r");
  465. X    if (hfp == NULL) {
  466. X#ifdef SYSLOG
  467. X        syslog(LOG_ERR, "gethistent: histfile: %m");
  468. X#endif SYSLOG
  469. X        return (NULL);
  470. X    }
  471. X
  472. X    len = strlen(msg_id);
  473. X    while (fgets(line, sizeof (line), hfp))
  474. X        if (!strncasecmp(msg_id, line, len))
  475. X            break;
  476. X
  477. X    if (feof(hfp)) {
  478. X        (void) fclose(hfp);
  479. X        return (NULL);
  480. X    }
  481. X#else not USGHIST
  482. X#ifdef DBM
  483. X    if (!dbopen) {
  484. X        if (dbminit(historyfile) < 0) {
  485. X#ifdef SYSLOG
  486. X            syslog(LOG_ERR, "openartbyid: dbminit %s: %m",
  487. X                historyfile);
  488. X#endif SYSLOG
  489. X            return (NULL);
  490. X        } else
  491. X            dbopen = 1;
  492. X    }
  493. X#else    /* ndbm */
  494. X    if (db == NULL) {
  495. X        db = dbm_open(historyfile, O_RDONLY, 0);
  496. X        if (db == NULL) {
  497. X#ifdef SYSLOG
  498. X            syslog(LOG_ERR, "openartbyid: dbm_open %s: %m",
  499. X                historyfile);
  500. X#endif SYSLOG
  501. X            return (NULL);
  502. X        }
  503. X    }
  504. X#endif DBM
  505. X
  506. X    key.dptr = msg_id;
  507. X    key.dsize = strlen(msg_id) + 1;
  508. X
  509. X#ifdef DBM
  510. X    content = fetch(key);
  511. X#else    /* ndbm */
  512. X    content = dbm_fetch(db, key);
  513. X#endif DBM
  514. X    if (content.dptr == NULL)
  515. X        return (NULL);
  516. X
  517. X    if (hfp == NULL) {
  518. X        hfp = fopen(historyfile, "r");
  519. X        if (hfp == NULL) {
  520. X#ifdef SYSLOG
  521. X            syslog(LOG_ERR, "message: fopen %s: %m",
  522. X                historyfile);
  523. X#endif SYSLOG
  524. X            return (NULL);
  525. X        }
  526. X    }
  527. X
  528. X    bcopy(content.dptr, (char *)<mp, sizeof (long));
  529. X    if (fseek(hfp, ltmp, 0) < 0) {
  530. X#ifdef SYSLOG
  531. X        syslog(LOG_ERR, "message: fseek: %m");
  532. X#endif SYSLOG
  533. X        return (NULL);
  534. X    }
  535. X
  536. X    (void) fgets(line, sizeof(line), hfp);
  537. X#endif USGHIST
  538. X
  539. X    if ((cp = index(line, '\n')) != NULL)
  540. X        *cp = '\0';
  541. X    cp = index(line, '\t');
  542. X    if (cp != NULL)
  543. X        cp = index(cp+1, '\t');
  544. X    if (cp == NULL) {
  545. X#ifdef SYSLOG
  546. X        syslog(LOG_ERR,
  547. X        "message: malformed line in history file at %ld bytes, id %s",
  548. X            ltmp, msg_id);
  549. X#endif SYSLOG
  550. X        return (NULL);
  551. X    }
  552. X    tmp = cp+1;
  553. X
  554. X    if ((cp = index(tmp, ' ')) != NULL)
  555. X        *cp = '\0';
  556. X    
  557. X    while ((cp = index(tmp, '.')) != NULL)
  558. X        *cp = '/';
  559. X
  560. X    (void) strcpy(path, spooldir);
  561. X    (void) strcat(path, "/");
  562. X    (void) strcat(path, tmp);
  563. X
  564. X    return (path);
  565. X}
  566. X
  567. X/*
  568. X * openartbyid -- open an article by message-id.
  569. X *
  570. X *    Arguments:    "msg_id" is the message-id of the article
  571. X *            to open.
  572. X *
  573. X *    Returns:    File pointer to opened article, or NULL if
  574. X *            the article was not in the history file or
  575. X *            could not be opened.
  576. X *
  577. X *    Side effects:    Opens article.
  578. X */
  579. X
  580. FILE *
  581. openartbyid(msg_id)
  582. X    char    *msg_id;
  583. X{
  584. X    char    *path;
  585. X
  586. X    path = gethistent(msg_id);
  587. X    if (path != NULL)
  588. X        return (fopen(path, "r"));
  589. X    else
  590. X        return (NULL);
  591. X}
  592. X
  593. X
  594. X/*
  595. X * check_ngperm -- check to see if they're allowed to see this
  596. X * article by matching Newsgroups: and Distribution: line.
  597. X *
  598. X *    Parameters:    "fp" is the file pointer of this article.
  599. X *
  600. X *    Returns:    0 if they're not allowed to see it.
  601. X *            1 if they are.
  602. X *
  603. X *    Side effects:    None.
  604. X */
  605. X
  606. check_ngperm(fp)
  607. X    register FILE    *fp;
  608. X{
  609. X    char        buf[MAXBUFLEN];
  610. X    register char    *cp;
  611. X    static char    **ngarray;
  612. X    int        ngcount;
  613. X
  614. X    if (ngpermcount == 0)
  615. X        return (1);
  616. X
  617. X    while (fgets(buf, sizeof (buf), fp) != NULL) {
  618. X        if (buf[0] == '\n')        /* End of header */
  619. X            break;
  620. X        if (buf[0] != 'N' && buf[0] != 'n')
  621. X            continue;
  622. X        cp = index(buf, '\n');
  623. X        if (cp)
  624. X            *cp = '\0';
  625. X        cp = index(buf, ':');
  626. X        if (cp == NULL)
  627. X            continue;
  628. X        *cp = '\0';
  629. X        if (!strcasecmp(buf, "newsgroups")) {
  630. X            ngcount = get_nglist(&ngarray, cp+2);
  631. X            break;
  632. X        }
  633. X    }
  634. X
  635. X    (void) rewind(fp);
  636. X
  637. X    if (ngcount == 0)    /* Either no newgroups or null entry */
  638. X        return (1);
  639. X
  640. X    return (ngmatch(s1strneql, ALLBUT,
  641. X        ngpermlist, ngpermcount, ngarray, ngcount));
  642. X}
  643. X
  644. X
  645. X/*
  646. X * spew -- spew out the contents of a file to stdout, doing
  647. X * the necessary cr-lf additions at the end.  Finish with
  648. X * a "." on a line by itself, and an fflush(stdout).
  649. X *
  650. X *    Parameters:    "how" tells what part of the file we
  651. X *            want spewed:
  652. X *                ARTICLE   The entire thing.
  653. X *                HEAD      Just the first part.
  654. X *                BODY      Just the second part.
  655. X *            "fp" is the open file to spew from.
  656. X *
  657. X *    Returns:    Nothing.
  658. X *
  659. X *    Side effects:    Changes current position in file.
  660. X */
  661. X
  662. spew(fp, how)
  663. X    FILE        *fp;
  664. X    int        how;
  665. X{
  666. X    char        line[NNTP_STRLEN];
  667. X    register char    *cp;
  668. X
  669. X#ifdef LOG
  670. X    ++arts_acsd;
  671. X#endif
  672. X
  673. X    if (how == STAT) {
  674. X        (void) fflush(stdout);
  675. X        return;
  676. X    }
  677. X
  678. X    while (fgets(line, sizeof(line)-6, fp) != NULL && *line != '\n') {
  679. X        if (how == BODY)    /* We need to skip this anyway */
  680. X            continue;
  681. X        cp = index(line, '\n');
  682. X        if (cp != NULL)
  683. X            *cp = '\0';
  684. X        if (*line == '.')
  685. X            putchar('.');
  686. X        putline(line);
  687. X        if (cp == NULL) {
  688. X            for (;;) {
  689. X                if ((fgets(line, sizeof(line)-6, fp) == NULL)
  690. X                    || (index(line, '\n') != NULL))
  691. X                    break;
  692. X            }
  693. X        }
  694. X    }
  695. X
  696. X    if (how == HEAD) {
  697. X        putchar('.');
  698. X        putchar('\r');
  699. X        putchar('\n');
  700. X        (void) fflush(stdout);
  701. X        return;
  702. X    } else if (how == ARTICLE) {
  703. X        putchar('\r');
  704. X        putchar('\n');
  705. X    }
  706. X
  707. X    while (fgets(line, sizeof(line)-6, fp) != NULL) {
  708. X        cp = index(line, '\n');
  709. X        if (cp != NULL)
  710. X            *cp = '\0';
  711. X        if (*line == '.')
  712. X            putchar('.');
  713. X        putline(line);
  714. X
  715. X        if (cp == NULL) {
  716. X            for (;;) {
  717. X                if ((fgets(line, sizeof(line)-6, fp) == NULL)
  718. X                    || (index(line, '\n') != NULL))
  719. X                    break;
  720. X            }
  721. X        }
  722. X    }
  723. X    putchar('.');
  724. X    putchar('\r');
  725. X    putchar('\n');
  726. X    (void) fflush(stdout);
  727. X}
  728. X
  729. X
  730. X/*
  731. X * get_id -- get the message id of the current article.
  732. X *
  733. X *    Parameters:    "art_fp" is a pointer to the open file.
  734. X *            "id" is space for the message ID.
  735. X *
  736. X *    Returns:    Nothing.
  737. X *
  738. X *    Side effects:    Seeks and rewinds on "art_fp".
  739. X *            Changes space pointed to by "id".
  740. X */
  741. X
  742. get_id(art_fp, id)
  743. X    register FILE    *art_fp;
  744. X    char        *id;
  745. X{
  746. X    char        line[MAXBUFLEN];
  747. X    register char    *cp;
  748. X
  749. X    while (fgets(line, sizeof(line), art_fp) != NULL) {
  750. X        if (*line == '\n')
  751. X            break;
  752. X        if (*line == 'M' || *line == 'm') {    /* "Message-ID" */
  753. X            if ((cp = index(line, ' ')) != NULL) {
  754. X                *cp = '\0';
  755. X                if (!strcasecmp(line, "Message-ID:")) {
  756. X                    (void) strcpy(id, cp + 1);
  757. X                    if ((cp = index(id, '\n')) != NULL)
  758. X                        *cp = '\0';
  759. X                    (void) rewind(art_fp);
  760. X                    return;
  761. X                }
  762. X            }
  763. X        }
  764. X    }
  765. X    (void) rewind(art_fp);
  766. X    (void) strcpy(id, "<0>");
  767. X}
  768. X        
  769. X
  770. X/*
  771. X * close_crnt -- close the current article file pointer, if it's
  772. X *    open.
  773. X *
  774. X *    Parameters:    None.
  775. X *
  776. X *    Returns:    Nothing.
  777. X *
  778. X *    Side effects:    Closes "art_fp" if it's open; sets "art_fp" to NULL.
  779. X */
  780. X
  781. close_crnt()
  782. X{
  783. X    if (art_fp != NULL)
  784. X        (void) fclose(art_fp);
  785. X    art_fp = NULL;
  786. X}
  787. X
  788. X
  789. X/*
  790. X * findart -- find an article number in the article array.
  791. X *
  792. X *    Parameters:    "artname" is a string containing
  793. X *            the name of the article.
  794. X *
  795. X *    Returns:    An index into "art_array",
  796. X *            or -1 if "artname" isn't in "art_array".
  797. X *            
  798. X *    Side effects:    None.
  799. X *
  800. X *    Improvement:    Replace this linear search with a binary one.
  801. X */
  802. X
  803. findart(artname)
  804. X    char        *artname;
  805. X{
  806. X    register int    i, artnum;
  807. X
  808. X    artnum = atoi(artname);
  809. X
  810. X    for (i = 0; i < num_arts; ++i)
  811. X        if (art_array[i] == artnum)
  812. X            return(i);
  813. X
  814. X    return (-1);
  815. X}
  816. X
  817. X
  818. X/*
  819. X * get_distlist -- return a nicely set up array of distribution groups
  820. X * along with a count, when given an NNTP-spec distribution list
  821. X * in the form <dist1,dist2,...,distn>.
  822. X *
  823. X *    Parameters:        "array" is storage for our array,
  824. X *                set to point at some static data.
  825. X *                "list" is the NNTP distribution list.
  826. X *
  827. X *    Returns:        Number of distributions found.
  828. X *                -1 on error.
  829. X *
  830. X *    Side effects:        Changes static data area.
  831. X */
  832. X
  833. get_distlist(array, list)
  834. X    char        ***array;
  835. X    char        *list;
  836. X{
  837. X    char        *cp;
  838. X    int        distcount;
  839. X    static char    **dist_list = (char **) NULL;
  840. X
  841. X    if (list[0] != '<')
  842. X        return (-1);
  843. X
  844. X    cp = index(list + 1, '>');
  845. X    if (cp != NULL)
  846. X        *cp = '\0';
  847. X    else
  848. X        return (-1);
  849. X
  850. X    for (cp = list + 1; *cp != '\0'; ++cp)
  851. X        if (*cp == ',')
  852. X            *cp = ' ';
  853. X    distcount = parsit(list + 1, &dist_list);
  854. X    *array = dist_list;
  855. X    return (distcount);
  856. X}
  857. X
  858. X
  859. X/*
  860. X * lower -- convert a character to lower case, if it's upper case.
  861. X *
  862. X *    Parameters:    "c" is the character to be
  863. X *            converted.
  864. X *
  865. X *    Returns:    "c" if the character is not
  866. X *            upper case, otherwise the lower
  867. X *            case eqivalent of "c".
  868. X *
  869. X *    Side effects:    None.
  870. X */
  871. X
  872. char
  873. lower(c)
  874. X    register char    c;
  875. X{
  876. X    if (isascii(c) && isupper(c))
  877. X        c = c - 'A' + 'a';
  878. X    return (c);
  879. X}
  880. X
  881. X
  882. X/* the following is from news 2.11 */
  883. X
  884. X#ifdef USG
  885. X/*
  886. X** Generate the appropriate history subfile name
  887. X*/
  888. char *
  889. histfile(hline)
  890. char *hline;
  891. X{
  892. X    char chr;    /* least significant digit of article number */
  893. X    static char subfile[BUFSIZ];
  894. X
  895. X    chr = findhfdigit(hline);
  896. X    sprintf(subfile, "%s.d/%c", HISTORY_FILE, chr);
  897. X    return subfile;
  898. X}
  899. X
  900. findhfdigit(fn)
  901. char *fn;
  902. X{
  903. X    register char *p;
  904. X    register int chr;
  905. X
  906. X    p = index(fn, '@');
  907. X    if (p != NULL && p > fn)
  908. X        chr = *(p - 1);
  909. X    else
  910. X        chr = '0';
  911. X    if (!isdigit(chr))
  912. X        chr = '0';
  913. X    return chr;
  914. X}
  915. bcopy(s, d, l)
  916. X    register char *s, *d;
  917. X    register int l;
  918. X{
  919. X    while (l-- > 0)
  920. X        *d++ = *s++;
  921. X}
  922. X
  923. bcmp(s1, s2, l)
  924. X    register char *s1, *s2;
  925. X    register int l;
  926. X{
  927. X    if (l == 0)
  928. X        return (0);
  929. X
  930. X    do
  931. X        if (*s1++ != *s2++)
  932. X            break;
  933. X    while (--l);
  934. X
  935. X    return (l);
  936. X}
  937. X
  938. bzero(p, l)
  939. X    register char *p;
  940. X    register int l;
  941. X{
  942. X    while (l-- > 0)
  943. X        *p++ = 0;
  944. X}
  945. X
  946. dup2(x,y)
  947. int x,y;
  948. X{ 
  949. X    close(y); 
  950. X    return(fcntl(x, F_DUPFD,y ));
  951. X}
  952. X#endif USG
  953. END_OF_FILE
  954. if test 11174 -ne `wc -c <'./server/misc.c'`; then
  955.     echo shar: \"'./server/misc.c'\" unpacked with wrong size!
  956. fi
  957. # end of './server/misc.c'
  958. fi
  959. if test -f './support/nntp_awk' -a "${1}" != "-c" ; then 
  960.   echo shar: Will not clobber existing file \"'./support/nntp_awk'\"
  961. else
  962. echo shar: Extracting \"'./support/nntp_awk'\" \(12577 characters\)
  963. sed "s/^X//" >'./support/nntp_awk' <<'END_OF_FILE'
  964. X# an awk script 
  965. X# an NNTP log summary report generator
  966. X#
  967. X# NOTE: for systems that are not as yet using the new 4.3 BSD syslog
  968. X# (and therefore have nntp messages lumped with everything else), it
  969. X# would be best to invoke this script thusly:
  970. X#
  971. X#    egrep nntp syslog.old | awk -f nntp_awk > report_of_the_week
  972. X#
  973. X# because this script will include in the report all messages in the log
  974. X# that it does not recognize (on the assumption that they are errors to
  975. X# be dealt with by a human).
  976. X#
  977. X# Erik E. Fair <fair@ucbarpa.berkeley.edu>
  978. X# May 17, 1986 - Norwegian Independence Day
  979. X#
  980. X# Recognize some new things - February 22, 1987
  981. X# Erik E. Fair <fair@ucbarpa.berkeley.edu>
  982. X#
  983. X# fix "xmt is not an array" bug - March 11, 1987
  984. X# Change Elapsed/CPU fields to break out time values, HH:MM:SS
  985. X# Erik E. Fair <fair@ucbarpa.berkeley.edu>
  986. X#
  987. X# Add reporting for newnews commands - August 27, 1987
  988. X# Erik E. Fair <fair@ucbarpa.berkeley.edu>
  989. X#
  990. X# Add nntpxmit connection attempt counting/reporting - December 7, 1987
  991. X# Erik E. Fair <fair@ucbarpa.berkeley.edu>
  992. X#
  993. BEGIN{
  994. X    readers = 0;
  995. X    transmit = 0;
  996. X    receive = 0;
  997. X    polled = 0;
  998. X}
  999. X### Skip stderr reports from rnews
  1000. X{
  1001. X    n = split($6, path, "/");
  1002. X    if (path[n] == "rnews:") next;
  1003. X    n = split($7, path, "/");
  1004. X    if (path[n] == "rnews") next;
  1005. X    host = $6;
  1006. X}
  1007. X$7 == "group" {
  1008. X    readers = 1;
  1009. X    ng[$8]++;
  1010. X    next;
  1011. X}
  1012. X$7 == "ihave" {
  1013. X    receive = 1;
  1014. X    rec[host]++;
  1015. X    if ($9 == "accepted") {
  1016. X        rec_accept[host]++;
  1017. X        if ($10 == "failed") rec_failed[host]++;
  1018. X    } else if ($9 == "rejected") rec_refuse[host]++;
  1019. X    next;
  1020. X}
  1021. X# this is from version 1.4 of nntpd
  1022. X$7 == "ihave_stats" {
  1023. X    receive = 1;
  1024. X    rec[host] += $9 + $11 + $13;
  1025. X    rec_accept[host] += $9;
  1026. X    rec_refuse[host] += $11;
  1027. X    rec_failed[host] += $13;
  1028. X    next;
  1029. X}
  1030. X$7 == "connect" {
  1031. X    systems[host]++;
  1032. X    next;
  1033. X}
  1034. X# nntpxmit connection errors
  1035. X# Ooooh! I *wish* awk had N dimensional arrays,
  1036. X# so I wouldn't have to throw away the error message here!
  1037. X$7 == "hello:" {
  1038. X    conn[host]++;
  1039. X    if ($8 == "Connection" && $9 == "refused")
  1040. X        rmt_fail[host]++;
  1041. X    else
  1042. X        open_fail[host]++;
  1043. X    next;
  1044. X}
  1045. X# we'll get stats from this, don't count conn[]
  1046. X$7 == "xfer:" {
  1047. X    open_fail[host]++;
  1048. X# since these are expected to be few in number, we still print
  1049. X# the exact error (no "next;" statement here).
  1050. X}
  1051. X$7 == "greeted" {
  1052. X    conn[host]++;
  1053. X    rmt_fail[host]++;
  1054. X    next;
  1055. X}
  1056. X$7 == "host" && $8 == "unknown" {
  1057. X    conn[host]++;
  1058. X    ns_fail[host]++;
  1059. X    next;
  1060. X}
  1061. X# nntpd connection abort - all "broken pipe" right now
  1062. X$7 == "disconnect:" { next }
  1063. X# syslogd shit
  1064. X$7 == "repeated" { next }
  1065. X# inews shit
  1066. X$11 == "spooled" { next }
  1067. X$7 == "exit" {
  1068. X    if ($8 > 0) readers = 1;
  1069. X    articles[host] += $8;
  1070. X    groups[host] += $10;
  1071. X    next;
  1072. X}
  1073. X$7 == "xmit" {
  1074. X    xmt_cpu[host] += $9 + $11;
  1075. X    xmt_ela[host] += $13;
  1076. X    next;
  1077. X}
  1078. X$7 == "times" {
  1079. X    cpu[host] += $9 + $11;
  1080. X    ela[host] += $13;
  1081. X    next;
  1082. X}
  1083. X$7 == "stats" {
  1084. X    transmit = 1;
  1085. X    conn[host]++;
  1086. X    xmt[host] += $8;
  1087. X    xmt_accept[host] += $10;
  1088. X    xmt_refuse[host] += $12;
  1089. X    xmt_failed[host] += $14;
  1090. X    next;
  1091. X}
  1092. X#
  1093. X#    For the Nth time, I wish awk had two dimensional associative
  1094. X#    arrays. I assume that the last request is the same as all the
  1095. X#    others in this section of logfile.
  1096. X#
  1097. X$7 == "newnews" {
  1098. X    polled = 1;
  1099. X    poll[host] ++;
  1100. X    poll_asked[host] = $8;
  1101. X    next;
  1102. X}
  1103. X$7 == "newnews_stats" {
  1104. X    poll_offered[host] += $9;
  1105. X    poll_took[host] += $11;
  1106. X    next;
  1107. X}
  1108. X$7 == "post" {
  1109. X    readers = 1;
  1110. X    post[host]++;
  1111. X    next;
  1112. X}
  1113. X$7 == "timeout" {
  1114. X    timeout[host]++;
  1115. X    timeouts = 1;
  1116. X    next;
  1117. X}
  1118. X$7 == "unrecognized" {
  1119. X    unknown[host] = 1;
  1120. X    curious = 1;
  1121. X}
  1122. X### Print anything that we don't recognize in the report
  1123. X{
  1124. X    print;
  1125. X}
  1126. END{
  1127. X    printf("\n");
  1128. X###############################################################################
  1129. X### Article Exchange With Peers (other servers) Statistics                  ###
  1130. X###############################################################################
  1131. X    if (transmit || receive || polled)
  1132. X        printf("NNTP peer article transfers\n\n");
  1133. X
  1134. X    if (polled) for(s in poll) servers[s]++;
  1135. X    if (receive) for(s in rec) servers[s]++;
  1136. X    if (transmit) for(s in xmt) servers[s]++;
  1137. X
  1138. X    if (receive) {
  1139. X        printf("Article Reception (they contact us)\n");
  1140. X        printf("System                  Offered  Took  Toss  Fail Toss   Elapsed       CPU  Pct\n");
  1141. X        for(s in rec) {
  1142. X
  1143. X            nrec += rec[s];
  1144. X            nrec_accept += rec_accept[s];
  1145. X            nrec_refuse += rec_refuse[s];
  1146. X            nrec_failed += rec_failed[s];
  1147. X            nrec_cpu += cpu[s];
  1148. X            nrec_ela += ela[s];
  1149. X
  1150. X            they_offered = rec[s];
  1151. X            if (they_offered == 0) they_offered = 1;
  1152. X            we_toss = (rec_refuse[s] / they_offered) * 100 + 0.5;
  1153. X
  1154. X            e_hours      = ela[s] / 3600;
  1155. X            e_sec        = ela[s] % 3600;
  1156. X            e_min        = e_sec / 60;
  1157. X            e_sec        %= 60;
  1158. X
  1159. X            c_hours      = cpu[s] / 3600;
  1160. X            c_sec        = cpu[s] % 3600;
  1161. X            c_min        = c_sec / 60;
  1162. X            c_sec        %= 60;
  1163. X
  1164. X            tmp = ela[s];
  1165. X            if (tmp == 0) tmp = 1;
  1166. X            pct = ((cpu[s] / tmp) * 100.0 + 0.5);
  1167. X
  1168. X            printf("%-25s %5d %5d %5d %5d %3d%% %3d:%02d:%02d %3d:%02d:%02d %3d%%\n", s, rec[s], rec_accept[s], rec_refuse[s], rec_failed[s], we_toss, e_hours, e_min, e_sec, c_hours, c_min, c_sec, pct);
  1169. X        }
  1170. X
  1171. X        e_hours      = nrec_ela / 3600;
  1172. X        e_sec        = nrec_ela % 3600;
  1173. X        e_min        = e_sec / 60;
  1174. X        e_sec        %= 60;
  1175. X
  1176. X        c_hours      = nrec_cpu / 3600;
  1177. X        c_sec        = nrec_cpu % 3600;
  1178. X        c_min        = c_sec / 60;
  1179. X        c_sec        %= 60;
  1180. X
  1181. X        they_offered = nrec;
  1182. X        if (they_offered == 0) they_offered = 1;
  1183. X        we_toss = (nrec_refuse / they_offered) * 100 + 0.5;
  1184. X
  1185. X        if (nrec_ela == 0) nrec_ela = 1;
  1186. X        pct = ((nrec_cpu / nrec_ela) * 100.0 + 0.5);
  1187. X
  1188. X        printf("\n%-25s %5d %5d %5d %5d %3d%% %3d:%02d:%02d %3d:%02d:%02d %3d%%\n\n", "TOTALS", nrec, nrec_accept, nrec_refuse, nrec_failed, we_toss, e_hours, e_min, e_sec, c_hours, c_min, c_sec, pct);
  1189. X    }
  1190. X
  1191. X###############################################################################
  1192. X    if (polled) {
  1193. X        printf("Article Transmission (they poll us)\n");
  1194. X        printf("System                     Conn Offrd  Took   Elapsed       CPU  Pct  Groups\n");
  1195. X        npoll = 0;
  1196. X        npoll_offered = 0;
  1197. X        npoll_took = 0;
  1198. X        npoll_cpu = 0;
  1199. X        npoll_ela = 0;
  1200. X
  1201. X        for(s in poll) {
  1202. X            npoll += poll[s];
  1203. X            npoll_offered += poll_offered[s];
  1204. X            npoll_took += poll_took[s];
  1205. X
  1206. X            if (rec[s]) {
  1207. X                printf("%-25s %5d %5d %5d  (see Article Reception)  %s\n", s, poll[s], poll_offered[s], poll_took[s], poll_asked[s]);
  1208. X            } else {
  1209. X                npoll_ela += ela[s];
  1210. X                npoll_cpu += cpu[s];
  1211. X
  1212. X                e_hours = ela[s] / 3600;
  1213. X                e_sec   = ela[s] % 3600;
  1214. X                e_min   = e_sec / 60;
  1215. X                e_sec   %= 60;
  1216. X
  1217. X                c_hours = cpu[s] / 3600;
  1218. X                c_sec   = cpu[s] % 3600;
  1219. X                c_min   = c_sec / 60;
  1220. X                c_sec   %= 60;
  1221. X
  1222. X                tmp = ela[s];
  1223. X                if (tmp == 0) tmp = 1;
  1224. X                pct = ((cpu[s] / tmp) * 100.0 + 0.5);
  1225. X
  1226. X                printf("%-25s %5d %5d %5d %3d:%02d:%02d %3d:%02d:%02d %3d%%  %s\n", s, poll[s], poll_offered[s], poll_took[s], e_hours, e_min, e_sec, c_hours, c_min, c_sec, pct, poll_asked[s]);
  1227. X            }
  1228. X        }
  1229. X        printf("\n%-25s %5d %5d %5d", "TOTALS", npoll, npoll_offered, npoll_took);
  1230. X        if (npoll_ela > 0 && npoll_cpu > 0) {
  1231. X
  1232. X            e_hours = npoll_ela / 3600;
  1233. X            e_sec   = npoll_ela % 3600;
  1234. X            e_min   = e_sec / 60;
  1235. X            e_sec   %= 60;
  1236. X
  1237. X            c_hours = npoll_cpu / 3600;
  1238. X            c_sec   = npoll_cpu % 3600;
  1239. X            c_min   = c_sec / 60;
  1240. X            c_sec   %= 60;
  1241. X
  1242. X            tmp = npoll_ela;
  1243. X            if (tmp == 0) tmp = 1;
  1244. X            pct = ((npoll_cpu / tmp) * 100.0 + 0.5);
  1245. X
  1246. X            printf(" %3d:%02d:%02d %3d:%02d:%02d %3d%%\n\n", e_hours, e_min, e_sec, c_hours, c_min, c_sec, pct);
  1247. X        } else
  1248. X            printf("\n\n");
  1249. X    }
  1250. X
  1251. X###############################################################################
  1252. X    if (transmit) {
  1253. X        printf("Article Transmission (we contact them)\n");
  1254. X        printf("System                    Offrd  Took  Toss  Fail  Pct   Elapsed       CPU  Pct\n");
  1255. X        for(s in xmt) {
  1256. X            we_offered = xmt[s];
  1257. X            if (we_offered == 0) we_offered = 1;
  1258. X            they_toss = (xmt_refuse[s] / we_offered) * 100 + 0.5;
  1259. X
  1260. X            e_hours = xmt_ela[s] / 3600;
  1261. X            e_sec   = xmt_ela[s] % 3600;
  1262. X            e_min   = e_sec / 60;
  1263. X            e_sec   %= 60;
  1264. X
  1265. X            c_hours = xmt_cpu[s] / 3600;
  1266. X            c_sec   = xmt_cpu[s] % 3600;
  1267. X            c_min   = c_sec / 60;
  1268. X            c_sec   %= 60;
  1269. X
  1270. X            elapsed = xmt_ela[s];
  1271. X            if (elapsed == 0) elapsed = 1;
  1272. X            pct = ((xmt_cpu[s] / elapsed) * 100.0 + 0.5);
  1273. X
  1274. X            printf("%-25s %5d %5d %5d %5d %3d%% %3d:%02d:%02d %3d:%02d:%02d %3d%%\n", s, xmt[s], xmt_accept[s], xmt_refuse[s], xmt_failed[s], they_toss, e_hours, e_min, e_sec, c_hours, c_min, c_sec, pct);
  1275. X
  1276. X            nxmt        += xmt[s];
  1277. X            nxmt_accept += xmt_accept[s];
  1278. X            nxmt_refuse += xmt_refuse[s];
  1279. X            nxmt_failed += xmt_failed[s];
  1280. X            nxmt_ela    += xmt_ela[s];
  1281. X            nxmt_cpu    += xmt_cpu[s];
  1282. X        }
  1283. X
  1284. X        we_offered = nxmt;
  1285. X        if (we_offered == 0) we_offered = 1;
  1286. X        they_toss = (nxmt_refuse / we_offered) * 100 + 0.5;
  1287. X
  1288. X        e_hours = nxmt_ela / 3600;
  1289. X        e_sec   = nxmt_ela % 3600;
  1290. X        e_min   = e_sec / 60;
  1291. X        e_sec   %= 60;
  1292. X
  1293. X        c_hours = nxmt_cpu / 3600;
  1294. X        c_sec   = nxmt_cpu % 3600;
  1295. X        c_min   = c_sec / 60;
  1296. X        c_sec   %= 60;
  1297. X
  1298. X        if (nxmt_ela == 0) nxmt_ela = 1;
  1299. X        pct = ((nxmt_cpu / nxmt_ela) * 100.0 + 0.5);
  1300. X
  1301. X        printf("\n%-25s %5d %5d %5d %5d %3d%% %3d:%02d:%02d %3d:%02d:%02d %3d%%\n\n", "TOTALS", nxmt, nxmt_accept, nxmt_refuse, nxmt_failed, they_toss, e_hours, e_min, e_sec, c_hours, c_min, c_sec, pct);
  1302. X
  1303. X        printf("Transmission Connection Attempts         ------errors-------\n");
  1304. X        printf("System                     Conn    OK    NS   Net   Rmt  Pct\n");
  1305. X        for(s in xmt) {
  1306. X            tot = conn[s];
  1307. X            if (tot == 0) tot = 1;
  1308. X            errs = rmt_fail[s] + ns_fail[s] + open_fail[s];
  1309. X            ok = (conn[s] - errs);
  1310. X            printf("%-25s %5d %5d %5d %5d %5d %3d%%\n", s, conn[s], ok, ns_fail[s], open_fail[s], rmt_fail[s], (100.0 * errs / tot + 0.5));
  1311. X            ct_tot += conn[s];
  1312. X            ct_ok  += ok;
  1313. X            ct_ns  += ns_fail[s];
  1314. X            ct_net += open_fail[s];
  1315. X            ct_rmt += rmt_fail[s];
  1316. X        }
  1317. X        tot = ct_tot;
  1318. X        if (tot == 0) tot = 1;
  1319. X        errs = ct_ns + ct_net + ct_rmt;
  1320. X        printf("\n%-25s %5d %5d %5d %5d %5d %3d%%\n\n", "TOTALS", ct_tot, ct_ok, ct_ns, ct_net, ct_rmt, (100.0 * errs / tot + 0.5));
  1321. X    }
  1322. X
  1323. X###############################################################################
  1324. X### Article Readership Statistics                                           ###
  1325. X###############################################################################
  1326. X
  1327. X    if (readers) {
  1328. X        printf("NNTP readership statistics\n");
  1329. X        printf("System                     Conn Articles Groups Post   Elapsed       CPU  Pct\n");
  1330. X        for(s in systems) {
  1331. X###
  1332. X### servers are different animals; they don't belong in this part of the report
  1333. X###
  1334. X            if (servers[s] > 0 && groups[s] == 0 && articles[s] == 0)
  1335. X                continue;
  1336. X###
  1337. X### report the curious server pokers elsewhere
  1338. X###
  1339. X            if (groups[s] == 0 && articles[s] == 0 && post[s] == 0) {
  1340. X                unknown[s] += systems[s];
  1341. X                curious = 1;
  1342. X                continue;
  1343. X            }
  1344. X
  1345. X            nconn += systems[s];
  1346. X            nart += articles[s];
  1347. X            ngrp += groups[s];
  1348. X            npost += post[s];
  1349. X            ncpu += cpu[s];
  1350. X            nela += ela[s];
  1351. X
  1352. X            e_hours      = ela[s] / 3600;
  1353. X            e_sec        = ela[s] % 3600;
  1354. X            e_min        = e_sec / 60;
  1355. X            e_sec        %= 60;
  1356. X
  1357. X            c_hours      = cpu[s] / 3600;
  1358. X            c_sec        = cpu[s] % 3600;
  1359. X            c_min        = c_sec / 60;
  1360. X            c_sec        %= 60;
  1361. X
  1362. X            elapsed = ela[s];
  1363. X            if (elapsed == 0) elapsed = 1;
  1364. X            pct = ((cpu[s] / elapsed) * 100 + 0.5);
  1365. X
  1366. X            printf("%-25s %5d %8d %6d %4d %3d:%02d:%02d %3d:%02d:%02d %3d%%\n", s, systems[s], articles[s], groups[s], post[s], e_hours, e_min, e_sec, c_hours, c_min, c_sec, pct);
  1367. X        }
  1368. X
  1369. X        e_hours      = nela / 3600;
  1370. X        e_sec        = nela % 3600;
  1371. X        e_min        = e_sec / 60;
  1372. X        e_sec        %= 60;
  1373. X
  1374. X        c_hours      = ncpu / 3600;
  1375. X        c_sec        = ncpu % 3600;
  1376. X        c_min        = c_sec / 60;
  1377. X        c_sec        %= 60;
  1378. X
  1379. X        if (nela == 0) nela = 1;
  1380. X        pct = ((ncpu / nela) * 100 + 0.5);
  1381. X
  1382. X        printf("\n%-25s %5d %8d %6d %4d %3d:%02d:%02d %3d:%02d:%02d %3d%%\n\n", "TOTALS", nconn, nart, ngrp, npost, e_hours, e_min, e_sec, c_hours, c_min, c_sec, pct);
  1383. X    }
  1384. X
  1385. X###############################################################################
  1386. X    if (curious) {
  1387. X        printf("Unknown NNTP server explorers\nSystem                     Conn\n");
  1388. X        for(s in unknown) {
  1389. X            printf("%-25s %5d\n", s, unknown[s]);
  1390. X        }
  1391. X        printf("\n");
  1392. X    }
  1393. X###############################################################################
  1394. X    if (timeouts) {
  1395. X        printf("Server timeouts\n");
  1396. X        for(s in timeout) {
  1397. X            printf("%-25s %5d\n", s, timeout[s]);
  1398. X        }
  1399. X        printf("\n");
  1400. X    }
  1401. X###############################################################################
  1402. X    if (readers) {
  1403. X        for(g in ng) {
  1404. X            x = length(g);
  1405. X            if (x > max) max = x;
  1406. X
  1407. X            i = index(g, ".");
  1408. X            if (i > 0) top = substr(g, 1, i - 1);
  1409. X            else top = g;
  1410. X            category[top] += ng[g];
  1411. X        }
  1412. X        fmt = sprintf("%%-%ds %%5d\n", max);
  1413. X
  1414. X        printf("Newsgroup Request Counts (by category)\n");
  1415. X        for(g in category) printf(fmt, g, category[g]);
  1416. X
  1417. X        printf("\nNewsgroup Request Counts (by newsgroup)\n");
  1418. X        for(g in ng) printf(fmt, g, ng[g]);
  1419. X        printf("\n");
  1420. X    }
  1421. X}
  1422. END_OF_FILE
  1423. if test 12577 -ne `wc -c <'./support/nntp_awk'`; then
  1424.     echo shar: \"'./support/nntp_awk'\" unpacked with wrong size!
  1425. fi
  1426. # end of './support/nntp_awk'
  1427. fi
  1428. if test -f './xmit/nntp_awk' -a "${1}" != "-c" ; then 
  1429.   echo shar: Will not clobber existing file \"'./xmit/nntp_awk'\"
  1430. else
  1431. echo shar: Extracting \"'./xmit/nntp_awk'\" \(12577 characters\)
  1432. sed "s/^X//" >'./xmit/nntp_awk' <<'END_OF_FILE'
  1433. X# an awk script 
  1434. X# an NNTP log summary report generator
  1435. X#
  1436. X# NOTE: for systems that are not as yet using the new 4.3 BSD syslog
  1437. X# (and therefore have nntp messages lumped with everything else), it
  1438. X# would be best to invoke this script thusly:
  1439. X#
  1440. X#    egrep nntp syslog.old | awk -f nntp_awk > report_of_the_week
  1441. X#
  1442. X# because this script will include in the report all messages in the log
  1443. X# that it does not recognize (on the assumption that they are errors to
  1444. X# be dealt with by a human).
  1445. X#
  1446. X# Erik E. Fair <fair@ucbarpa.berkeley.edu>
  1447. X# May 17, 1986 - Norwegian Independence Day
  1448. X#
  1449. X# Recognize some new things - February 22, 1987
  1450. X# Erik E. Fair <fair@ucbarpa.berkeley.edu>
  1451. X#
  1452. X# fix "xmt is not an array" bug - March 11, 1987
  1453. X# Change Elapsed/CPU fields to break out time values, HH:MM:SS
  1454. X# Erik E. Fair <fair@ucbarpa.berkeley.edu>
  1455. X#
  1456. X# Add reporting for newnews commands - August 27, 1987
  1457. X# Erik E. Fair <fair@ucbarpa.berkeley.edu>
  1458. X#
  1459. X# Add nntpxmit connection attempt counting/reporting - December 7, 1987
  1460. X# Erik E. Fair <fair@ucbarpa.berkeley.edu>
  1461. X#
  1462. BEGIN{
  1463. X    readers = 0;
  1464. X    transmit = 0;
  1465. X    receive = 0;
  1466. X    polled = 0;
  1467. X}
  1468. X### Skip stderr reports from rnews
  1469. X{
  1470. X    n = split($6, path, "/");
  1471. X    if (path[n] == "rnews:") next;
  1472. X    n = split($7, path, "/");
  1473. X    if (path[n] == "rnews") next;
  1474. X    host = $6;
  1475. X}
  1476. X$7 == "group" {
  1477. X    readers = 1;
  1478. X    ng[$8]++;
  1479. X    next;
  1480. X}
  1481. X$7 == "ihave" {
  1482. X    receive = 1;
  1483. X    rec[host]++;
  1484. X    if ($9 == "accepted") {
  1485. X        rec_accept[host]++;
  1486. X        if ($10 == "failed") rec_failed[host]++;
  1487. X    } else if ($9 == "rejected") rec_refuse[host]++;
  1488. X    next;
  1489. X}
  1490. X# this is from version 1.4 of nntpd
  1491. X$7 == "ihave_stats" {
  1492. X    receive = 1;
  1493. X    rec[host] += $9 + $11 + $13;
  1494. X    rec_accept[host] += $9;
  1495. X    rec_refuse[host] += $11;
  1496. X    rec_failed[host] += $13;
  1497. X    next;
  1498. X}
  1499. X$7 == "connect" {
  1500. X    systems[host]++;
  1501. X    next;
  1502. X}
  1503. X# nntpxmit connection errors
  1504. X# Ooooh! I *wish* awk had N dimensional arrays,
  1505. X# so I wouldn't have to throw away the error message here!
  1506. X$7 == "hello:" {
  1507. X    conn[host]++;
  1508. X    if ($8 == "Connection" && $9 == "refused")
  1509. X        rmt_fail[host]++;
  1510. X    else
  1511. X        open_fail[host]++;
  1512. X    next;
  1513. X}
  1514. X# we'll get stats from this, don't count conn[]
  1515. X$7 == "xfer:" {
  1516. X    open_fail[host]++;
  1517. X# since these are expected to be few in number, we still print
  1518. X# the exact error (no "next;" statement here).
  1519. X}
  1520. X$7 == "greeted" {
  1521. X    conn[host]++;
  1522. X    rmt_fail[host]++;
  1523. X    next;
  1524. X}
  1525. X$7 == "host" && $8 == "unknown" {
  1526. X    conn[host]++;
  1527. X    ns_fail[host]++;
  1528. X    next;
  1529. X}
  1530. X# nntpd connection abort - all "broken pipe" right now
  1531. X$7 == "disconnect:" { next }
  1532. X# syslogd shit
  1533. X$7 == "repeated" { next }
  1534. X# inews shit
  1535. X$11 == "spooled" { next }
  1536. X$7 == "exit" {
  1537. X    if ($8 > 0) readers = 1;
  1538. X    articles[host] += $8;
  1539. X    groups[host] += $10;
  1540. X    next;
  1541. X}
  1542. X$7 == "xmit" {
  1543. X    xmt_cpu[host] += $9 + $11;
  1544. X    xmt_ela[host] += $13;
  1545. X    next;
  1546. X}
  1547. X$7 == "times" {
  1548. X    cpu[host] += $9 + $11;
  1549. X    ela[host] += $13;
  1550. X    next;
  1551. X}
  1552. X$7 == "stats" {
  1553. X    transmit = 1;
  1554. X    conn[host]++;
  1555. X    xmt[host] += $8;
  1556. X    xmt_accept[host] += $10;
  1557. X    xmt_refuse[host] += $12;
  1558. X    xmt_failed[host] += $14;
  1559. X    next;
  1560. X}
  1561. X#
  1562. X#    For the Nth time, I wish awk had two dimensional associative
  1563. X#    arrays. I assume that the last request is the same as all the
  1564. X#    others in this section of logfile.
  1565. X#
  1566. X$7 == "newnews" {
  1567. X    polled = 1;
  1568. X    poll[host] ++;
  1569. X    poll_asked[host] = $8;
  1570. X    next;
  1571. X}
  1572. X$7 == "newnews_stats" {
  1573. X    poll_offered[host] += $9;
  1574. X    poll_took[host] += $11;
  1575. X    next;
  1576. X}
  1577. X$7 == "post" {
  1578. X    readers = 1;
  1579. X    post[host]++;
  1580. X    next;
  1581. X}
  1582. X$7 == "timeout" {
  1583. X    timeout[host]++;
  1584. X    timeouts = 1;
  1585. X    next;
  1586. X}
  1587. X$7 == "unrecognized" {
  1588. X    unknown[host] = 1;
  1589. X    curious = 1;
  1590. X}
  1591. X### Print anything that we don't recognize in the report
  1592. X{
  1593. X    print;
  1594. X}
  1595. END{
  1596. X    printf("\n");
  1597. X###############################################################################
  1598. X### Article Exchange With Peers (other servers) Statistics                  ###
  1599. X###############################################################################
  1600. X    if (transmit || receive || polled)
  1601. X        printf("NNTP peer article transfers\n\n");
  1602. X
  1603. X    if (polled) for(s in poll) servers[s]++;
  1604. X    if (receive) for(s in rec) servers[s]++;
  1605. X    if (transmit) for(s in xmt) servers[s]++;
  1606. X
  1607. X    if (receive) {
  1608. X        printf("Article Reception (they contact us)\n");
  1609. X        printf("System                  Offered  Took  Toss  Fail Toss   Elapsed       CPU  Pct\n");
  1610. X        for(s in rec) {
  1611. X
  1612. X            nrec += rec[s];
  1613. X            nrec_accept += rec_accept[s];
  1614. X            nrec_refuse += rec_refuse[s];
  1615. X            nrec_failed += rec_failed[s];
  1616. X            nrec_cpu += cpu[s];
  1617. X            nrec_ela += ela[s];
  1618. X
  1619. X            they_offered = rec[s];
  1620. X            if (they_offered == 0) they_offered = 1;
  1621. X            we_toss = (rec_refuse[s] / they_offered) * 100 + 0.5;
  1622. X
  1623. X            e_hours      = ela[s] / 3600;
  1624. X            e_sec        = ela[s] % 3600;
  1625. X            e_min        = e_sec / 60;
  1626. X            e_sec        %= 60;
  1627. X
  1628. X            c_hours      = cpu[s] / 3600;
  1629. X            c_sec        = cpu[s] % 3600;
  1630. X            c_min        = c_sec / 60;
  1631. X            c_sec        %= 60;
  1632. X
  1633. X            tmp = ela[s];
  1634. X            if (tmp == 0) tmp = 1;
  1635. X            pct = ((cpu[s] / tmp) * 100.0 + 0.5);
  1636. X
  1637. X            printf("%-25s %5d %5d %5d %5d %3d%% %3d:%02d:%02d %3d:%02d:%02d %3d%%\n", s, rec[s], rec_accept[s], rec_refuse[s], rec_failed[s], we_toss, e_hours, e_min, e_sec, c_hours, c_min, c_sec, pct);
  1638. X        }
  1639. X
  1640. X        e_hours      = nrec_ela / 3600;
  1641. X        e_sec        = nrec_ela % 3600;
  1642. X        e_min        = e_sec / 60;
  1643. X        e_sec        %= 60;
  1644. X
  1645. X        c_hours      = nrec_cpu / 3600;
  1646. X        c_sec        = nrec_cpu % 3600;
  1647. X        c_min        = c_sec / 60;
  1648. X        c_sec        %= 60;
  1649. X
  1650. X        they_offered = nrec;
  1651. X        if (they_offered == 0) they_offered = 1;
  1652. X        we_toss = (nrec_refuse / they_offered) * 100 + 0.5;
  1653. X
  1654. X        if (nrec_ela == 0) nrec_ela = 1;
  1655. X        pct = ((nrec_cpu / nrec_ela) * 100.0 + 0.5);
  1656. X
  1657. X        printf("\n%-25s %5d %5d %5d %5d %3d%% %3d:%02d:%02d %3d:%02d:%02d %3d%%\n\n", "TOTALS", nrec, nrec_accept, nrec_refuse, nrec_failed, we_toss, e_hours, e_min, e_sec, c_hours, c_min, c_sec, pct);
  1658. X    }
  1659. X
  1660. X###############################################################################
  1661. X    if (polled) {
  1662. X        printf("Article Transmission (they poll us)\n");
  1663. X        printf("System                     Conn Offrd  Took   Elapsed       CPU  Pct  Groups\n");
  1664. X        npoll = 0;
  1665. X        npoll_offered = 0;
  1666. X        npoll_took = 0;
  1667. X        npoll_cpu = 0;
  1668. X        npoll_ela = 0;
  1669. X
  1670. X        for(s in poll) {
  1671. X            npoll += poll[s];
  1672. X            npoll_offered += poll_offered[s];
  1673. X            npoll_took += poll_took[s];
  1674. X
  1675. X            if (rec[s]) {
  1676. X                printf("%-25s %5d %5d %5d  (see Article Reception)  %s\n", s, poll[s], poll_offered[s], poll_took[s], poll_asked[s]);
  1677. X            } else {
  1678. X                npoll_ela += ela[s];
  1679. X                npoll_cpu += cpu[s];
  1680. X
  1681. X                e_hours = ela[s] / 3600;
  1682. X                e_sec   = ela[s] % 3600;
  1683. X                e_min   = e_sec / 60;
  1684. X                e_sec   %= 60;
  1685. X
  1686. X                c_hours = cpu[s] / 3600;
  1687. X                c_sec   = cpu[s] % 3600;
  1688. X                c_min   = c_sec / 60;
  1689. X                c_sec   %= 60;
  1690. X
  1691. X                tmp = ela[s];
  1692. X                if (tmp == 0) tmp = 1;
  1693. X                pct = ((cpu[s] / tmp) * 100.0 + 0.5);
  1694. X
  1695. X                printf("%-25s %5d %5d %5d %3d:%02d:%02d %3d:%02d:%02d %3d%%  %s\n", s, poll[s], poll_offered[s], poll_took[s], e_hours, e_min, e_sec, c_hours, c_min, c_sec, pct, poll_asked[s]);
  1696. X            }
  1697. X        }
  1698. X        printf("\n%-25s %5d %5d %5d", "TOTALS", npoll, npoll_offered, npoll_took);
  1699. X        if (npoll_ela > 0 && npoll_cpu > 0) {
  1700. X
  1701. X            e_hours = npoll_ela / 3600;
  1702. X            e_sec   = npoll_ela % 3600;
  1703. X            e_min   = e_sec / 60;
  1704. X            e_sec   %= 60;
  1705. X
  1706. X            c_hours = npoll_cpu / 3600;
  1707. X            c_sec   = npoll_cpu % 3600;
  1708. X            c_min   = c_sec / 60;
  1709. X            c_sec   %= 60;
  1710. X
  1711. X            tmp = npoll_ela;
  1712. X            if (tmp == 0) tmp = 1;
  1713. X            pct = ((npoll_cpu / tmp) * 100.0 + 0.5);
  1714. X
  1715. X            printf(" %3d:%02d:%02d %3d:%02d:%02d %3d%%\n\n", e_hours, e_min, e_sec, c_hours, c_min, c_sec, pct);
  1716. X        } else
  1717. X            printf("\n\n");
  1718. X    }
  1719. X
  1720. X###############################################################################
  1721. X    if (transmit) {
  1722. X        printf("Article Transmission (we contact them)\n");
  1723. X        printf("System                    Offrd  Took  Toss  Fail  Pct   Elapsed       CPU  Pct\n");
  1724. X        for(s in xmt) {
  1725. X            we_offered = xmt[s];
  1726. X            if (we_offered == 0) we_offered = 1;
  1727. X            they_toss = (xmt_refuse[s] / we_offered) * 100 + 0.5;
  1728. X
  1729. X            e_hours = xmt_ela[s] / 3600;
  1730. X            e_sec   = xmt_ela[s] % 3600;
  1731. X            e_min   = e_sec / 60;
  1732. X            e_sec   %= 60;
  1733. X
  1734. X            c_hours = xmt_cpu[s] / 3600;
  1735. X            c_sec   = xmt_cpu[s] % 3600;
  1736. X            c_min   = c_sec / 60;
  1737. X            c_sec   %= 60;
  1738. X
  1739. X            elapsed = xmt_ela[s];
  1740. X            if (elapsed == 0) elapsed = 1;
  1741. X            pct = ((xmt_cpu[s] / elapsed) * 100.0 + 0.5);
  1742. X
  1743. X            printf("%-25s %5d %5d %5d %5d %3d%% %3d:%02d:%02d %3d:%02d:%02d %3d%%\n", s, xmt[s], xmt_accept[s], xmt_refuse[s], xmt_failed[s], they_toss, e_hours, e_min, e_sec, c_hours, c_min, c_sec, pct);
  1744. X
  1745. X            nxmt        += xmt[s];
  1746. X            nxmt_accept += xmt_accept[s];
  1747. X            nxmt_refuse += xmt_refuse[s];
  1748. X            nxmt_failed += xmt_failed[s];
  1749. X            nxmt_ela    += xmt_ela[s];
  1750. X            nxmt_cpu    += xmt_cpu[s];
  1751. X        }
  1752. X
  1753. X        we_offered = nxmt;
  1754. X        if (we_offered == 0) we_offered = 1;
  1755. X        they_toss = (nxmt_refuse / we_offered) * 100 + 0.5;
  1756. X
  1757. X        e_hours = nxmt_ela / 3600;
  1758. X        e_sec   = nxmt_ela % 3600;
  1759. X        e_min   = e_sec / 60;
  1760. X        e_sec   %= 60;
  1761. X
  1762. X        c_hours = nxmt_cpu / 3600;
  1763. X        c_sec   = nxmt_cpu % 3600;
  1764. X        c_min   = c_sec / 60;
  1765. X        c_sec   %= 60;
  1766. X
  1767. X        if (nxmt_ela == 0) nxmt_ela = 1;
  1768. X        pct = ((nxmt_cpu / nxmt_ela) * 100.0 + 0.5);
  1769. X
  1770. X        printf("\n%-25s %5d %5d %5d %5d %3d%% %3d:%02d:%02d %3d:%02d:%02d %3d%%\n\n", "TOTALS", nxmt, nxmt_accept, nxmt_refuse, nxmt_failed, they_toss, e_hours, e_min, e_sec, c_hours, c_min, c_sec, pct);
  1771. X
  1772. X        printf("Transmission Connection Attempts         ------errors-------\n");
  1773. X        printf("System                     Conn    OK    NS   Net   Rmt  Pct\n");
  1774. X        for(s in xmt) {
  1775. X            tot = conn[s];
  1776. X            if (tot == 0) tot = 1;
  1777. X            errs = rmt_fail[s] + ns_fail[s] + open_fail[s];
  1778. X            ok = (conn[s] - errs);
  1779. X            printf("%-25s %5d %5d %5d %5d %5d %3d%%\n", s, conn[s], ok, ns_fail[s], open_fail[s], rmt_fail[s], (100.0 * errs / tot + 0.5));
  1780. X            ct_tot += conn[s];
  1781. X            ct_ok  += ok;
  1782. X            ct_ns  += ns_fail[s];
  1783. X            ct_net += open_fail[s];
  1784. X            ct_rmt += rmt_fail[s];
  1785. X        }
  1786. X        tot = ct_tot;
  1787. X        if (tot == 0) tot = 1;
  1788. X        errs = ct_ns + ct_net + ct_rmt;
  1789. X        printf("\n%-25s %5d %5d %5d %5d %5d %3d%%\n\n", "TOTALS", ct_tot, ct_ok, ct_ns, ct_net, ct_rmt, (100.0 * errs / tot + 0.5));
  1790. X    }
  1791. X
  1792. X###############################################################################
  1793. X### Article Readership Statistics                                           ###
  1794. X###############################################################################
  1795. X
  1796. X    if (readers) {
  1797. X        printf("NNTP readership statistics\n");
  1798. X        printf("System                     Conn Articles Groups Post   Elapsed       CPU  Pct\n");
  1799. X        for(s in systems) {
  1800. X###
  1801. X### servers are different animals; they don't belong in this part of the report
  1802. X###
  1803. X            if (servers[s] > 0 && groups[s] == 0 && articles[s] == 0)
  1804. X                continue;
  1805. X###
  1806. X### report the curious server pokers elsewhere
  1807. X###
  1808. X            if (groups[s] == 0 && articles[s] == 0 && post[s] == 0) {
  1809. X                unknown[s] += systems[s];
  1810. X                curious = 1;
  1811. X                continue;
  1812. X            }
  1813. X
  1814. X            nconn += systems[s];
  1815. X            nart += articles[s];
  1816. X            ngrp += groups[s];
  1817. X            npost += post[s];
  1818. X            ncpu += cpu[s];
  1819. X            nela += ela[s];
  1820. X
  1821. X            e_hours      = ela[s] / 3600;
  1822. X            e_sec        = ela[s] % 3600;
  1823. X            e_min        = e_sec / 60;
  1824. X            e_sec        %= 60;
  1825. X
  1826. X            c_hours      = cpu[s] / 3600;
  1827. X            c_sec        = cpu[s] % 3600;
  1828. X            c_min        = c_sec / 60;
  1829. X            c_sec        %= 60;
  1830. X
  1831. X            elapsed = ela[s];
  1832. X            if (elapsed == 0) elapsed = 1;
  1833. X            pct = ((cpu[s] / elapsed) * 100 + 0.5);
  1834. X
  1835. X            printf("%-25s %5d %8d %6d %4d %3d:%02d:%02d %3d:%02d:%02d %3d%%\n", s, systems[s], articles[s], groups[s], post[s], e_hours, e_min, e_sec, c_hours, c_min, c_sec, pct);
  1836. X        }
  1837. X
  1838. X        e_hours      = nela / 3600;
  1839. X        e_sec        = nela % 3600;
  1840. X        e_min        = e_sec / 60;
  1841. X        e_sec        %= 60;
  1842. X
  1843. X        c_hours      = ncpu / 3600;
  1844. X        c_sec        = ncpu % 3600;
  1845. X        c_min        = c_sec / 60;
  1846. X        c_sec        %= 60;
  1847. X
  1848. X        if (nela == 0) nela = 1;
  1849. X        pct = ((ncpu / nela) * 100 + 0.5);
  1850. X
  1851. X        printf("\n%-25s %5d %8d %6d %4d %3d:%02d:%02d %3d:%02d:%02d %3d%%\n\n", "TOTALS", nconn, nart, ngrp, npost, e_hours, e_min, e_sec, c_hours, c_min, c_sec, pct);
  1852. X    }
  1853. X
  1854. X###############################################################################
  1855. X    if (curious) {
  1856. X        printf("Unknown NNTP server explorers\nSystem                     Conn\n");
  1857. X        for(s in unknown) {
  1858. X            printf("%-25s %5d\n", s, unknown[s]);
  1859. X        }
  1860. X        printf("\n");
  1861. X    }
  1862. X###############################################################################
  1863. X    if (timeouts) {
  1864. X        printf("Server timeouts\n");
  1865. X        for(s in timeout) {
  1866. X            printf("%-25s %5d\n", s, timeout[s]);
  1867. X        }
  1868. X        printf("\n");
  1869. X    }
  1870. X###############################################################################
  1871. X    if (readers) {
  1872. X        for(g in ng) {
  1873. X            x = length(g);
  1874. X            if (x > max) max = x;
  1875. X
  1876. X            i = index(g, ".");
  1877. X            if (i > 0) top = substr(g, 1, i - 1);
  1878. X            else top = g;
  1879. X            category[top] += ng[g];
  1880. X        }
  1881. X        fmt = sprintf("%%-%ds %%5d\n", max);
  1882. X
  1883. X        printf("Newsgroup Request Counts (by category)\n");
  1884. X        for(g in category) printf(fmt, g, category[g]);
  1885. X
  1886. X        printf("\nNewsgroup Request Counts (by newsgroup)\n");
  1887. X        for(g in ng) printf(fmt, g, ng[g]);
  1888. X        printf("\n");
  1889. X    }
  1890. X}
  1891. END_OF_FILE
  1892. if test 12577 -ne `wc -c <'./xmit/nntp_awk'`; then
  1893.     echo shar: \"'./xmit/nntp_awk'\" unpacked with wrong size!
  1894. fi
  1895. # end of './xmit/nntp_awk'
  1896. fi
  1897. echo shar: End of archive 7 \(of 9\).
  1898. cp /dev/null ark7isdone
  1899. MISSING=""
  1900. for I in 1 2 3 4 5 6 7 8 9 ; do
  1901.     if test ! -f ark${I}isdone ; then
  1902.     MISSING="${MISSING} ${I}"
  1903.     fi
  1904. done
  1905. if test "${MISSING}" = "" ; then
  1906.     echo You have unpacked all 9 archives.
  1907.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1908. else
  1909.     echo You still need to unpack the following archives:
  1910.     echo "        " ${MISSING}
  1911. fi
  1912. ##  End of shell archive.
  1913. exit 0
  1914.